//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2006
//
// 'Map properties' dialog, 'Extras' page.
//

# include "StdAfx.h"
# include "Resource.h"
# include "MapProperties.h"
# include "Map.h"
# include "ChangeMapHeader.h"
# include "ExtraSections.h"
# include "ListView.h"
# include "ParseHelpers.h"
# include "EditText.h"
# include "EditKVPair.h"

/*static
const char * _GetValue (const char * _pKey, const char * _pEnd) {
	if (_pKey >= _pEnd)
		return _pEnd;
	const char * const p = reinterpret_cast<char *> (::memchr (_pKey, '=', _pEnd - _pKey));
	return p ? p + 1 : _pEnd;
}*/

static
map_header_t::extra_t::iterator _FindExtra (size_t _cItem) {
	size_t cItem = 0;
	for (map_header_t::extra_t::iterator ei = g_map.Header.extra.begin (); ei != g_map.Header.extra.end (); ++ ei) {
		if (cItem == _cItem)
			return ei;
		++ cItem;
	}
	return g_map.Header.extra.end ();
}

static
void _FillExtras (HWND _hExtras, size_t _cSel = -1) {
	ListView_DeleteAllItems (_hExtras);

	size_t cItem = 0;
	for (map_header_t::extra_t::const_iterator ei = g_map.Header.extra.begin (); ei != g_map.Header.extra.end (); ++ ei) {
		InsertItem     (_hExtras, cItem, cItem, "%s", ei->first. c_str ());
		SetSubItemText (_hExtras, cItem, 1,     "%s", ei->second.c_str ());
		++ cItem;
	}

	AutoSizeColumns (_hExtras);

	if (_cSel != -1) {
		SetSelection (_hExtras, _cSel);
		EnsureSelectionVisible (_hExtras);
	}
}

INT_PTR CALLBACK _MapExtrasProc (HWND _hWnd, UINT _uMsg, WPARAM _wParam, LPARAM _lParam) {
	switch (_uMsg) {
		case WM_INITDIALOG: {
			CCritSec::CLock lock (g_cs);

			//
			// Extras.
			//

			const HWND hExtras = ::GetDlgItem (_hWnd, IDC_EXTRAS);

			ListView_SetExtendedListViewStyleEx (hExtras, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);

			AddColumn (hExtras, 0, "Key");
			AddColumn (hExtras, 1, "Value");

			_FillExtras (hExtras);

			//
			// Extra sections.
			//

			const HWND hSections = ::GetDlgItem (_hWnd, IDC_EXTRA_SECTIONS);

			size_t cItem = 0;
			for (sections_t::iterator i = g_map.ExtraSections.begin (); i != g_map.ExtraSections.end (); ++ i) {
				const char * p = i->strText.c_str ();
				const char * const pEnd = i->strText.c_str () + i->strText.size ();
		
				do {
					OmitSpaces (& p, pEnd);
					if (p [0] == ';')
						p = FindNextLine (p, pEnd);
				} while (p [0] != '[' && p < pEnd);
				if (p == pEnd)
					continue;

				const char * const pNextLine = FindNextLine (p, pEnd);
				InsertItem (hSections, cItem, reinterpret_cast<LPARAM> (& * i), "%s", string_t (p, GetLineLen (p, pNextLine)).c_str ());
				++ cItem;
			}

			if (g_map.ExtraSections.empty ())
				::EnableWindow (hSections, FALSE);

			// Buttons.
			::EnableWindow (::GetDlgItem (_hWnd, IDC_DELETE), FALSE);
			::EnableWindow (::GetDlgItem (_hWnd, IDC_EDIT),   FALSE);

			return TRUE;
		}

		case WM_COMMAND: {
			switch (LOWORD (_wParam)) {
				case IDC_ADD: {
					string_t strKey, strValue;
					if (EditKVPair (_hWnd, strKey, strValue, "Add Extra")) {
						if (! strKey.empty ()) {
							AddMapHeaderExtra (strKey, strValue);

							const HWND hExtras = ::GetDlgItem (_hWnd, IDC_EXTRAS);
							_FillExtras (hExtras);
						}
					}
					return TRUE;
				}

				case IDC_DELETE: {
					const HWND hExtras = ::GetDlgItem (_hWnd, IDC_EXTRAS);
					const size_t cSel = ListView_GetSelectionMark (hExtras);
					if (cSel != -1) {
						const size_t cIdx = GetLParam (hExtras, cSel);
						const map_header_t::extra_t::iterator ei = _FindExtra (cIdx);
						if (ei != g_map.Header.extra.end ()) {
							DeleteMapHeaderExtra (ei->first);
							_FillExtras (hExtras, cSel + 1);
						}
					}
					return TRUE;
				}

				case IDC_EDIT: {
					const HWND hExtras = ::GetDlgItem (_hWnd, IDC_EXTRAS);
					const size_t cSel = ListView_GetSelectionMark (hExtras);
					if (cSel != -1) {
						const size_t cIdx = GetLParam (hExtras, cSel);
						const map_header_t::extra_t::iterator ei = _FindExtra (cIdx);
						if (ei != g_map.Header.extra.end ()) {
							string_t strValue = ei->second;
							if (EditText (_hWnd, strValue, "Edit Value", false)) {
								EditMapHeaderExtra (ei->first, strValue);
								_FillExtras (hExtras, cSel);
							}
						}
					}

					return TRUE;
				}
			}
			break;
		}

		case WM_NOTIFY: {
			const NMHDR * const pInfo = reinterpret_cast<const NMHDR *> (_lParam);
			switch (pInfo->code) {
				case LVN_ITEMCHANGED: {
					const NMLISTVIEW * const pInfo2 = reinterpret_cast<const NMLISTVIEW *> (_lParam);
					if (
						(pInfo2->uOldState & LVIS_SELECTED) == 0 &&
						(pInfo2->uNewState & LVIS_SELECTED) != 0
					) {
						::EnableWindow (::GetDlgItem (_hWnd, IDC_DELETE), TRUE);
						::EnableWindow (::GetDlgItem (_hWnd, IDC_EDIT),   TRUE);
					}
					break;
				}

				case NM_RETURN:
				case NM_DBLCLK: {
					const NMITEMACTIVATE * const pInfo2 = reinterpret_cast<const NMITEMACTIVATE *> (_lParam);

					if (pInfo->idFrom == IDC_EXTRA_SECTIONS) {
						const HWND hSections = ::GetDlgItem (_hWnd, IDC_EXTRA_SECTIONS);
						section_t * const pSection = reinterpret_cast<section_t *> (GetLParam (hSections, pInfo2->iItem));

						string_t strText = pSection->strText;
						if (EditText (_hWnd, strText, "Edit Source", true))
							SetExtraSection (* pSection, strText);
					} else if (pInfo->idFrom == IDC_EXTRAS) {
						::SendMessage (_hWnd, WM_COMMAND, IDC_EDIT, 0);
					}
					break;
				}
			}
			break;
		}
	}

	return FALSE;
}
